package net.zrnecko.km;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;

@SuppressWarnings("serial")
@Singleton
public class GuiceRemoteServiceServlet extends RemoteServiceServlet {

	// TODO may be removed?
	@Inject
	private Injector injector;
	
	@Inject
	private Logger log;
	
	@Override
	public void init() throws ServletException {
		// TODO Auto-generated method stub
		super.init();
		log.setLevel(Level.INFO);
		log.info("Initializing RPC dispatcher servlet...");
	}

	@Override
	public String processCall(String payload) throws SerializationException {
		try {
			log.info("Incoming payload: " + payload);
			RPCRequest req = RPC.decodeRequest(payload, null, this);

			log.info("Processing call for " + req.getMethod().getDeclaringClass() + " service.");
			RemoteService service = getServiceInstance(req.getMethod()
					.getDeclaringClass());

			String response = RPC.invokeAndEncodeResponse(service, req.getMethod(), req
					.getParameters(), req.getSerializationPolicy());
			log.info("Returning " + response );
			return response;
		} catch (IncompatibleRemoteServiceException ex) {
			log(
					"IncompatibleRemoteServiceException in the processCall(String) method.",
					ex);
			return RPC.encodeResponseForFailure(null, ex);
		}
	}

	@SuppressWarnings( { "unchecked" })
	private RemoteService getServiceInstance(Class serviceClass) {
		return (RemoteService) injector.getInstance(serviceClass);
	}
}